package web.common.internal.jdo.engine;

import org.springframework.jdbc.core.JdbcTemplate;
import web.common.core.io.ClassScanner;
import web.common.internal.jdo.dialect.DetectDialect;
import web.common.internal.jdo.parser.ParserFactory;
import web.common.jdo.engine.Jdo;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Jin Zheng
 * @since 1.0 2022-01-12
 */
public class JdoBuilder {
	private DataSource dataSource;
	private JdbcTemplate jdbcTemplate;
	private boolean escape;
	private ParserFactory parserFactory;
	private Jdo jdo;
	private final List<Class<?>> clazzList = new ArrayList<>();
	private final List<String> pkgList = new ArrayList<>();

	public JdoBuilder() {
	}

	public Jdo build() {
		var dialect = DetectDialect.dialect(dataSource);
		this.parserFactory = new ParserFactory(dialect, escape);
		this.jdo = new DefaultJdo(parserFactory, jdbcTemplate);

		this.parseClazz();
		return jdo;
	}

	private void parseClazz() {
		for (var clazz : clazzList) {
			parserFactory.parse(clazz);
		}
		ClassScanner scanner = ClassScanner.create(c -> parserFactory.parse(c));
		scanner.scan(pkgList);
	}

	public JdoBuilder setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
		return this;
	}

	public JdoBuilder setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
		return this;
	}

	public JdoBuilder setEscape(boolean escape) {
		this.escape = escape;
		return this;
	}

	public JdoBuilder addClazz(Class<?>... clazzes) {
		for (var clazz : clazzes) {
			if (!clazzList.contains(clazz)) {
				clazzList.add(clazz);
			}
		}
		return this;
	}

	public JdoBuilder addScanPackages(String... pkgs) {
		for (var pkg : pkgs) {
			if (!pkgList.contains(pkg)) {
				pkgList.add(pkg);
			}
		}
		return this;
	}

	public JdoBuilder addScanPackages(List<String> pkgs) {
		for (var pkg : pkgs) {
			if (!pkgList.contains(pkg)) {
				pkgList.add(pkg);
			}
		}
		return this;
	}

	public ParserFactory getParserFactory() {
		return parserFactory;
	}

	public Jdo getJdo() {
		return jdo;
	}

}
